#pragma once

#include "CallPutCombinationsAnalysis.h"
#include "CsvFileReader.h"
#include "Warrant.h"

#include <iostream>
namespace
{
    Warrant::Type GetType( const std::string& type )
    {
        if( type == "CALL" ) 
            return Warrant::call;
        else if( type == "PUT" )
            return Warrant::put;
    
        throw std::runtime_error( "invalid warrant type" );
    }
}

int main(int argc, char* argv[]) 
{
    try
    {
        if( argc != 4 )
            throw std::invalid_argument( "XXX.exe separator inputDataFilePath outputFilePath" );

        std::string separator = argv[1];
        std::string inputDataFilePath = argv[2];
        std::string outputFilePath = argv[3];

        CsvFileReader dataReader( separator, inputDataFilePath );
        CallPutCombinationsAnalysis CallPuts( separator, outputFilePath );

        while( dataReader.ReadRow() )
        {
            // ignore other type
            if( dataReader.GetStringData( "Call/Put" ) == "CALL" || dataReader.GetStringData( "Call/Put" ) == "PUT" )
            {
                CallPuts.AddWarrant( Warrant( dataReader.GetStringData( "Underlying Code" ),
                                              GetType( dataReader.GetStringData( "Call/Put" ) ),
                                              dataReader.GetStringData( "Code" ),
                                              dataReader.GetDoubleData( "Strike" ),
                                              dataReader.GetDoubleData( "Ask(HKD)" ),
                                              dataReader.GetDoubleData( "Ratio" ) ) );
            }
        }

        CallPuts.PrintCombinations( );
    }
    catch( std::invalid_argument e )
    {
        std::cout <<std::endl << e.what() <<std::endl ;
    }
    catch( std::runtime_error e )
    {
        std::cout <<std::endl << e.what() <<std::endl ;
    }
    catch( ... )
    {
        std::cout <<std::endl << "unknown exception thrown"<<std::endl ;
    }
}